#pragma once
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include <functional>
#include <sys/wait.h>
#include "Task.hpp"
#include"Channel.hpp"
enum
{
    OK,
    PIPEERROR,
    FORKERROR,
    USAGEERROR
};
using work_t = std::function<void()>;
class ProcessPool
{
public:
    ProcessPool(int n,work_t w)
    :processnum(n)
    ,work(w)
    {

    }
    ~ProcessPool()
    {}
int InitProcessPoll()
{
    for (int i = 0; i < processnum; i++) // 创建子进程
    {
        int fds[2] = {0};
        int n = pipe(fds);
        if (n < 0)
        {
            std::cout << "pipe error" << std::endl;
            return PIPEERROR;
        }
        pid_t id = fork();
        if (id < 0)
        {
            std::cout << "fork error" << std::endl;
            return FORKERROR;
        }
        if (id == 0)
        {
            for(auto &c : channels)
            {
                c.Close();
            }
            ::close(fds[1]);
            dup2(fds[0], 0);
            // char buffer[1024];
            //  while (true)
            //  {
            //      size_t n = ::read(fds[0], buffer, 1024);
            //      if (n > 0)
            //      {
            //          buffer[n] = '\0';
            //          std::cout << "child->father,message: " << buffer << std::endl;
            //      }
            //      sleep(1);
            //  }
            //  std::cout<<"child pid: "<<getpid()<<std::endl;
            work();
            ::exit(0);
        }
        // int cnt = 0;
        // while (true)
        // {
        //     std::string message = "hello world, hello ";
        //     message += std::to_string(getpid());
        //     message += ", ";
        //     message += std::to_string(cnt);
        //     cnt++;
        //     ::write(fds[1], message.c_str(), message.size());
        //     sleep(1);
        // }
        ::close(fds[0]);
        channels.emplace_back(fds[1], id);
        // pid_t rid = waitpid(id, nullptr, 0);
    }
    return OK;
}
void DispatchTask()
{
    int who = 0;
    int num = 5;
    while (num--)
    {
        int task = tm.SelecTack();
        Channel &curr = channels[who++];
        who %= channels.size();
        std::cout << "######################" << std::endl;
        std::cout << "send " << task << " to " << curr.Name() << ", 任务还剩: " << num << std::endl;
        std::cout << "######################" << std::endl;
        curr.Send(task);
        sleep(1);
    }
}
void CleanProcessPool()
{
    for(auto &c : channels)
    {
        c.Close();
        pid_t rid = waitpid(c.Id(),nullptr,0);
        if(rid > 0)
        {
            std::cout<<"child: "<<rid<<" quit... success"<<std::endl;
        }
    }
    // for(auto &c : channels)
    // {
    //     pid_t rid = waitpid(c.Id(),nullptr,0);
    //     if(rid > 0)
    //     {
    //         std::cout<<"child: "<<rid<<" quit... success"<<std::endl;
    //     }
    // }
}
void DbugPrint()
{
    for (auto c : channels)
    {
        std::cout << c.Name() << std::endl;
    }
}
private:
    std::vector<Channel> channels;
    int processnum;
    work_t work;
};
